#####################################################################
# Product:      KnowledgeEngine (Plone Edition)
#
# File:         CountryEntitySource.py
#
# Copyright:    Copyright (c) 2006, Faulkner Technologies
#
# Author:       Brian Oliver
#
# Description:  An 'EntitySource' that provides 'Country' entities.
#
# See Also:     Entity, *EntityChooser, *EntitySource
#####################################################################

#####################################################################
## Zope Library Imports
from Globals import InitializeClass
from AccessControl import ClassSecurityInfo
from AccessControl.Role import RoleManager
 
#####################################################################
## Python Library Imports
# (none)

#####################################################################
## Knowledge Engine Library Imports
from Products.KnowledgeEngine.Common import *
from Products.KnowledgeEngine.Core import *
from Products.KnowledgeEngine.Entity import Entity
from Products.KnowledgeEngine.PropertyDefinition import *
from Products.KnowledgeEngine.PropertyTypes import *
from Products.KnowledgeEngine.PropertyFormats import *
from Products.KnowledgeEngine.PropertyStructures import *
from Products.KnowledgeEngine.EventDefinition import *
from Products.KnowledgeEngine.PermissionDefinition import *
from Products.KnowledgeEngine.EntitySource import EntitySource, EntitySourceInfo

#####################################################################
## CMF Library Imports
from Products.CMFCore import permissions
from Products.CMFCore.ActionInformation import ActionInformation
from Products.CMFCore.utils import getToolByName

#####################################################################
## Zope Library Imports
from Globals import DTMLFile
from Globals import Persistent
from App.ImageFile import ImageFile
from Products.ZSQLMethods.SQL import SQL
from DateTime import DateTime
from AccessControl import ClassSecurityInfo

#####################################################################
## Python Library Imports
import os
import base64
import binascii

#####################################################################
## CountryEntitySourceInfo Class Definition
class CountryEntitySourceInfo(EntitySourceInfo):
    """
        Defines the class info methods, defining information about
        the class without needing an instance of the class
    """

    #---------------------------------------------------------------#

    def getClassName(self):
        """
            Returns the name of the class for which
            we are providing information.
        """
        return 'CountryEntitySource'

    #---------------------------------------------------------------#

    def getDisplayName(self):
        """
            Return a friendly name for the class instances
            (this is used for displaying in lists etc)
        """

        return "CountryEntitySource"

    #---------------------------------------------------------------#

    def getDescription(self):
        """
            ABSTRACT: Return a friendly description on the purpose
            of this class.  This description is often used in the
            Property Editor for instances of this class
        """

        return "Defines a source for ISO country entities"

    #---------------------------------------------------------------#

    def getIdentityType(self):
        """
            Return the identity type.
        """

        return "esCountries"

    #---------------------------------------------------------------#

    def getClassIcon(self):
        """
            Return the appropriate icon file for the class.
        """

        return ImageFile('skins/CountryEntitySource_icon.gif', globals())

    #---------------------------------------------------------------#

    def isContainer(self):
        """
            Returns if the instance is providing folderish/container
            services.

            Override an return true if the instance is to be
            a container for other instances.

            NOTE: all instances support "events" so there is no
            need to return true if you require "event" support.
        """

        return false

    #---------------------------------------------------------------#

    def isPermittedInContainer(self, containerClassInfo, containerInstance = None, instance=None):
        """
            ABSTRACT: Returns if class instances (instance) is permitted in
            the specified container (containerInstance)

            NOTE: This is from this class' instance perspective.
        """

        #CountryEntitySources don't contain anything
        return false

    #---------------------------------------------------------------#

    def isChildPermitted(self, childClassInfo, childInstance = None):
        """
            Returns if the specified child is permitted as a
            child of the class' instances.

            NOTE: This is from this class' instance perspective.

            For component containers, this always overrides what the
            return value from childClassInfo.isPermittedInContainer(...)
        """

        #CountryEntitySources don't contain anything
        return false

    #---------------------------------------------------------------#

    def isPortalObject(self):
        """
            Returns if the object can be placed directly in 
            a Plone Portal (rather than like most objects
            that must exist within a GenericObject container
            object.
            
            eg: Models, EntitySources are Portal Objects.
        """
        
        return true

    #---------------------------------------------------------------#

    def onConfigureProperties(self):
        """
            Automatically called by the Knowledge Engine once
            the class has been loaded.  Use this method to register
            class specific properties using the PropertyReflection interface.

            If this class is sub-classed, a call must be made to
            the super-class to ensure super-class properties are
            correctly registered

            NOTE: This method is called before ClassInfo.onAfterStartup()
        """

        #initialise the super-class properties for reflection
        EntitySourceInfo.onConfigureProperties(self)

    #---------------------------------------------------------------#

    def onConfigureEvents(self):
        """
            Automatically called by the Knowledge Engine once
            the class has been loaded.  Use this method to register
            class specific events using the EventReflection interface.

            If this class is sub-classed, a call must be made to
            the super-class to ensure super-class properties are
            correctly registered

            NOTE: This method is called before ClassInfo.onAfterStartup()
        """

        #initialise the super-class events for reflection
        EntitySourceInfo.onConfigureEvents(self)

    #---------------------------------------------------------------#

    def onConfigurePermissions(self):
        """
            Automatically called by the Knowledge Engine once
            the class has been loaded.  Use this method to register
            class specific permission definitions.

            If this class is sub-classed, a call must be made to
            the super-class to ensure super-class properties are
            correctly registered

            NOTE: This method is called before ClassInfo.onAfterStartup()
        """

        #initialise the super-class permissions for reflection
        EntitySourceInfo.onConfigurePermissions(self)

    #---------------------------------------------------------------#

#####################################################################
## CountryEntitySource Class Definition
class CountryEntitySource(EntitySource):
    """
        ISO Country Entity Source
    """

    security = ClassSecurityInfo()

    #---------------------------------------------------------------#

    #ABSTRACT TRANSIENT: a ClassInfo implementation instance to provide info about this class
    _CLASSINFO = CountryEntitySourceInfo()

    #---------------------------------------------------------------#
    # Default Attribute Values
    meta_type = 'CountryEntitySource'

    #the countries
    isoCountries = [Entity("AFG","Afghanistan"),
                    Entity("ALB","Albania"),
                    Entity("DZA","Algeria"),
                    Entity("ASM","American Samoa"),
                    Entity("AND","Andorra"),
                    Entity("AGO","Angola"),
                    Entity("AIA","Anguilla"),
                    Entity("ATA","Antarctica"),
                    Entity("ATG","Antigua and Barbuda"),
                    Entity("ARG","Argentina"),
                    Entity("ARM","Armenia"),
                    Entity("ABW","Aruba"),
                    Entity("AUS","Australia"),
                    Entity("AUT","Austria"),
                    Entity("AZE","Azerbaijan"),
                    Entity("BHS","Bahamas"),
                    Entity("BHR","Bahrain"),
                    Entity("BGD","Bangladesh"),
                    Entity("BRB","Barbados"),
                    Entity("BLR","Belarus"),
                    Entity("BEL","Belgium"),
                    Entity("BLZ","Belize"),
                    Entity("BEN","Benin"),
                    Entity("BMU","Bermuda"),
                    Entity("BTN","Bhutan"),
                    Entity("BOL","Bolivia"),
                    Entity("BWA","Botswana"),
                    Entity("BVT","Bouvet Island"),
                    Entity("BRA","Brazil"),
                    Entity("IOT","British Indian Ocean Territory"),
                    Entity("BRN","Brunei Darussalam"),
                    Entity("BGR","Bulgaria"),
                    Entity("BFA","Burkina Faso"),
                    Entity("BDI","Burundi"),
                    Entity("KHM","Cambodia"),
                    Entity("CMR","Cameroon"),
                    Entity("CAN","Canada"),
                    Entity("CPV","Cape Verde"),
                    Entity("CYM","Cayman Islands"),
                    Entity("CAF","Central African Republic"),
                    Entity("TCD","Chad"),
                    Entity("CHL","Chile"),
                    Entity("CHN","China"),
                    Entity("CXR","Christmas Island"),
                    Entity("CCK","Cocos (Keeling) Islands"),
                    Entity("COL","Colombia"),
                    Entity("COM","Comoros"),
                    Entity("COG","Congo"),
                    Entity("COK","Cook Islands"),
                    Entity("CRI","Costa Rica"),
                    Entity("CIV","Cote D'ivoire"),
                    Entity("CUB","Cuba"),
                    Entity("CYP","Cyprus"),
                    Entity("CZE","Czech Republic"),
                    Entity("DNK","Denmark"),
                    Entity("DJI","Djibouti"),
                    Entity("DMA","Dominica"),
                    Entity("DOM","Dominican Republic"),
                    Entity("ECU","Ecuador"),
                    Entity("EGY","Egypt"),
                    Entity("SLV","El Salvador"),
                    Entity("GNQ","Equatorial Guinea"),
                    Entity("ERI","Eritrea"),
                    Entity("EST","Estonia"),
                    Entity("ETH","Ethiopia"),
                    Entity("FRO","Faroe Islands"),
                    Entity("FLK","Falkland Islands (Malvinas)"),
                    Entity("FJI","Fiji"),
                    Entity("FIN","Finland"),
                    Entity("FRA","France"),
                    Entity("GUF","French Guiana"),
                    Entity("PYF","French Polynesia"),
                    Entity("ATF","French Southern Territories"),
                    Entity("GAB","Gabon"),
                    Entity("GMB","Gambia"),
                    Entity("GEO","Georgia"),
                    Entity("DEU","Germany"),
                    Entity("GHA","Ghana"),
                    Entity("GIB","Gibraltar"),
                    Entity("GRC","Greece"),
                    Entity("GRL","Greenland"),
                    Entity("GRD","Grenada"),
                    Entity("GLP","Guadeloupe"),
                    Entity("GUM","Guam"),
                    Entity("GTM","Guatemala"),
                    Entity("GIN","Guinea"),
                    Entity("GNB","Guinea-Bissau"),
                    Entity("GUY","Guyana"),
                    Entity("HTI","Haiti"),
                    Entity("VAT","Holy See (Vatican City State)"),
                    Entity("HND","Honduras"),
                    Entity("HKG","Hong Kong"),
                    Entity("HUN","Hungary"),
                    Entity("ISL","Iceland"),
                    Entity("IND","India"),
                    Entity("IDN","Indonesia"),
                    Entity("IRQ","Iraq"),
                    Entity("IRL","Ireland"),
                    Entity("ISR","Israel"),
                    Entity("ITA","Italy"),
                    Entity("JAM","Jamaica"),
                    Entity("JPN","Japan"),
                    Entity("JOR","Jordan"),
                    Entity("KAZ","Kazakhstan"),
                    Entity("KEN","Kenya"),
                    Entity("KIR","Kiribati"),
                    Entity("PKR","Korea, Democratic People's Republic of"),
                    Entity("KOR","Korea, Republic of"),
                    Entity("KWT","Kuwait"),
                    Entity("KGZ","Kyrgyzstan"),
                    Entity("LAO","Lao People's Democratic Republic"),
                    Entity("LVA","Latvia"),
                    Entity("LBN","Lebanon"),
                    Entity("LSO","Lesotho"),
                    Entity("LBR","Liberia"),
                    Entity("LBY","Libyan Arab Jamahiriya"),
                    Entity("LIE","Liechtenstein"),
                    Entity("LTU","Lithuania"),
                    Entity("LUX","Luxembourg"),
                    Entity("MDG","Madagascar"),
                    Entity("MWI","Malawi"),
                    Entity("MYS","Malaysia"),
                    Entity("MDV","Maldives"),
                    Entity("MLI","Mali"),
                    Entity("MLT","Malta"),
                    Entity("MHL","Marshall Islands"),
                    Entity("MTQ","Martinique"),
                    Entity("MRT","Mauritania"),
                    Entity("MUS","Mauritius"),
                    Entity("MYT","Mayotte"),
                    Entity("MEX","Mexico"),
                    Entity("MCO","Monaco"),
                    Entity("MNG","Mongolia"),
                    Entity("MSR","Montserrat"),
                    Entity("MAR","Morocco"),
                    Entity("MOZ","Mozambique"),
                    Entity("MMR","Myanmar"),
                    Entity("NAM","Namibia"),
                    Entity("NRU","Nauru"),
                    Entity("NPL","Nepal"),
                    Entity("NLD","Netherlands"),
                    Entity("ANT","Netherlands Antilles"),
                    Entity("NCL","New Caledonia"),
                    Entity("NZL","New Zealand"),
                    Entity("NIC","Nicaragua"),
                    Entity("NER","Niger"),
                    Entity("NGA","Nigeria"),
                    Entity("NIU","Niue"),
                    Entity("NFK","Norfolk Island"),
                    Entity("MNP","Northern Mariana Islands"),
                    Entity("NOR","Norway"),
                    Entity("OMN","Oman"),
                    Entity("PAK","Pakistan"),
                    Entity("PLW","Palau"),
                    Entity("PSE","Palestinian Territory"),
                    Entity("PAN","Panama"),
                    Entity("PNG","Papua New Guinea"),
                    Entity("PRY","Paraguay"),
                    Entity("PER","Peru"),
                    Entity("PHL","Philippines"),
                    Entity("PCN","Pitcairn"),
                    Entity("POL","Poland"),
                    Entity("PRT","Portugal"),
                    Entity("PRI","Puerto Rico"),
                    Entity("QAT","Qatar"),
                    Entity("REU","Reunion"),
                    Entity("ROM","Romania"),
                    Entity("RUS","Russian Federation"),
                    Entity("RWA","Rwanda"),
                    Entity("SHN","Saint Helena"),
                    Entity("KNA","Saint Kitts And Nevis"),
                    Entity("LCA","Saint Lucia"),
                    Entity("SPM","Saint Pierre and Miquelon"),
                    Entity("VCT","Saint Vincent And The Grenadines"),
                    Entity("WSM","Samoa"),
                    Entity("SMR","San Marino"),
                    Entity("STP","Sao Tome And Principe"),
                    Entity("SAU","Saudi Arabia"),
                    Entity("SEN","Senegal"),
                    Entity("SYC","Seychelles"),
                    Entity("SLE","Sierra Leone"),
                    Entity("SGP","Singapore"),
                    Entity("SVN","Slovenia"),
                    Entity("SLB","Solomon Islands"),
                    Entity("SOM","Somalia"),
                    Entity("ZAF","South Africa"),
                    Entity("ESP","Spain"),
                    Entity("LKA","Sri Lanka"),
                    Entity("SDN","Sudan"),
                    Entity("SUR","Suriname"),
                    Entity("SWZ","Swaziland"),
                    Entity("SWE","Sweden"),
                    Entity("CHE","Switzerland"),
                    Entity("SYR","Syrian Arab Republic"),
                    Entity("TJK","Tajikistan"),
                    Entity("THA","Thailand"),
                    Entity("TLS","Timor-Leste"),
                    Entity("TGO","Togo"),
                    Entity("TKL","Tokelau"),
                    Entity("TON","Tonga"),
                    Entity("TTO","Trinidad And Tobago"),
                    Entity("TUN","Tunisia"),
                    Entity("TUR","Turkey"),
                    Entity("TKM","Turkmenistan"),
                    Entity("TCA","Turks And Caicos Islands"),
                    Entity("TUV","Tuvalu"),
                    Entity("UGA","Uganda"),
                    Entity("UKR","Ukraine"),
                    Entity("ARE","United Arab Emirates"),
                    Entity("GBR","United Kingdom"),
                    Entity("USA","United States"),
                    Entity("UMI","United States Minor Outlying Islands"),
                    Entity("URY","Uruguay"),
                    Entity("UZB","Uzbekistan"),
                    Entity("VUT","Vanuatu"),
                    Entity("VEN","Venezuela"),
                    Entity("VNM","Viet Nam"),
                    Entity("COD","Congo, Democratic Republic of the"),
                    Entity("ESH","Western Sahara"),
                    Entity("YEM","Yemen"),
                    Entity("YUG","Yugoslavia"),
                    Entity("ZMB","Zambia"),
                    Entity("ZWE","Zimbabwe"),
                    Entity("BIH","Bosnia and Herzegovina"),
                    Entity("FSM","Micronesia"),
                    Entity("HMD","Heard And Mc Donald Islands"),
                    Entity("HRV","Croatia (Hrvatska)"),
                    Entity("IRN","Iran (Islamic Republic Of)"),
                    Entity("MAC","Macau"),
                    Entity("MDA","Moldova"),
                    Entity("MKD","Macedonia, Former Yugoslav Republic"),
                    Entity("SGS","South Georgia & South Sandwich Islands"),
                    Entity("SJM","Svalbard And Jan Mayen Islands"),
                    Entity("SVK","Slovakia (Slovak Republic)"),
                    Entity("TMP","East Timor"),
                    Entity("TWN","Taiwan"),
                    Entity("TZA","Tanzania"),
                    Entity("VGB","Virgin Islands (British)"),
                    Entity("VIR","Virgin Islands (U.S.)"), 
                    Entity("WLF","Wallis And Futuna Islands")
                ]

    #---------------------------------------------------------------#

    def __init__(self, id, identity):
        "Constructor for the object"

        EntitySource.__init__(self, id, identity)

        #perform onAfterInstanciation
        self.onAfterInstanciation()

    #---------------------------------------------------------------#

    def onAfterInstanciation(self):
        """
            Handle Knowledge Engine specific actions after this object
            has been loaded into memory.

            This is useful for performing backwards compatibility
        """

        #perform default onAfterInstanciation for the container
        EntitySource.onAfterInstanciation(self)

    #---------------------------------------------------------------#

    def getNrEntities(self, user = None, filterBy = {}):
        """
            Returns the number of entities available from this
            CountryEntitySource for the specified user.
            
            The user (optional) is provided to enable CountryEntitySources to filter by user.
        """
 
        # Remove authenticatedUser from filterBy if it's present, as it has
        filterBy.pop('authenticatedUser', None)
       
        return len(self.isoCountries)

    #---------------------------------------------------------------#

    def getEntities(self, user = None, filterBy = {}):
        """
            Returns the entities from this entity source,
            ordered by entity identity.
        """

        # Remove authenticatedUser from filterBy if it's present, as it has
        filterBy.pop('authenticatedUser', None)
        
        sortedCountries = self.isoCountries
        sortedCountries.sort(lambda x,y : -(x.getTitle() < y.getTitle()))        
        return sortedCountries

    #---------------------------------------------------------------#

    def getEntitiesByBatch(self, batchNr, batchSize = 10, user = None, filterBy = {}):
        """
            Returns a batch of entities as specified.
            
            NOTE 1: The first available batch is 0
            
            NOTE 2: The entities are returned in order of their name
        """

        # Remove authenticatedUser from filterBy if it's present, as it has
        filterBy.pop('authenticatedUser', None)
        
        return self.getEntities()[batchNr * batchSize:batchSize]

    #---------------------------------------------------------------#

    def getEntity(self, entityIdentity, user = None):
        """
            Returns the entity with the specified identity
            for the provided user
        """
          
        #search for the entity
        entityList = [entity for entity in self.isoCountries if entity.getIdentity() == entityIdentity]
        
        if len(entityList) == 0:
            return None
        else:
            return entityList[0]
        
    #---------------------------------------------------------------#

    def getEntityNameSingular(self):
        """
            ABSTRACT: Return the name of a single entity provided 
            by the Entity Source
        """
        
        return "Country"
        
    #---------------------------------------------------------------#

    def getEntityNamePlural(self):
        """
            ABSTRACT: Return the name of a collection of entities provided 
            by the Entity Source
        """
        
        return "Countries"

    #---------------------------------------------------------------#

    def hasDefaultView(self):
        """
            PLONE Support:

            Returns if the object has a default view.  By setting this
            to true, a view tab will be added to the object.

            If this is false, attempting to visit the / (default view)
            for a component will redirect the client to the
            next available parent that has a default view.
        """

        return false
        
    #---------------------------------------------------------------#

#####################################################################
## Class Initialisation

#####################################################################
## CMF Required Class Initialisation

def addCountryEntitySource(self, id, REQUEST=None):
    """
        The Zope/CMF factory method to create an instance
    """

    #create a KnowledgeEngine identity for the new model
    identity = generateIdentity(CountryEntitySource.identity_type)

    #create an instance
    object = CountryEntitySource(id, identity)

    #add the object to the specified container (called self)
    self._setObject(id, object)

    if REQUEST is not None:
        REQUEST['RESPONSE'].redirect(object.absolute_url() + '/manage_main' )


#the CMF/Plone factory type information - used to create objects!)
factoryTypeInformation = {
                               'id'             : 'CountryEntitySource'
                             , 'meta_type'      : 'CountryEntitySource'
                             , 'description'    : "A KnowledgeEngine CountryEntitySource"
                             , 'icon'           : 'CountryEntitySource_icon.gif'
                             , 'product'        : 'KnowledgeEngine'
                             , 'factory'        : 'addCountryEntitySource'
                             , 'filter_content_types' : 0
                             , 'global_allow'   : 0
                             , 'immediate_view' : 'view'
                             , 'actions'        :
                                ( { 'id'            : 'view'
                                  , 'name'          : 'View'
                                  , 'action'        : 'string:${folder_url}/view'
                                  , 'permissions'   : (permissions.View,)
                                  , 'category'      : 'folder'
                                  }
                                ,
                                )
                         }

#####################################################################
## Class Initialisation

# Register Class Information with the KnowledgeEngine
registerPortalObjectClass(CountryEntitySource, addCountryEntitySource, factoryTypeInformation)

#####################################################################
